# -*- coding: utf-8 -*-

## Version Info:
## ---------------------------------------------------
## 1.10 - ADDED Ability to display/Modify files within a torrent..
##      - ADDED "remove+delete torrent" and "remove+delete torrent + data" options.
##      - ADDED Global-Options Menu This enables all Configuration options to be modified.
## 1.50 - Too Much to list..
## 1.51 - Added Elapsed and Eta to torrent Lists.
##      - Fixed Ratio to report correctly.
##      - Modified TorrentMgr to call DownloadMgr (Fixes problem when no default mgr selected first)

import  traceback,string,os
from    xbmcgui     import ListItem as xListItem
from    types       import *
from    time        import time as tTime    ,   sleep as tSleep
from    re          import findall as reFindall, compile as reCompile, DOTALL as reDotAll, search as reSearch

import  core

## Class to Control Azureus..
class Controller:
    def __init__(self,win,PathName):
        self.win                    =   win
        self._                      =   self.win._
        self.ClearVars()
        self.Version                =   '1.50'
        self.Dir                    =   'Azureus'
        self.Title                  =   'Azureus'
        self.FileType               =   'torrent'
        self.win.Title              =   self.Title
        self.FILEHASH               =   ''

        ## Azureus XML Strings
        self.Az_Xml                 =   {}
        self.Az_Xml['Begin']        =   '\n\r<REQUEST>'
        self.Az_Xml['End']          =   '\n\r</REQUEST>'
        self.Az_Xml['Method']       =   '\n\r\t<METHOD>%s</METHOD>'
        self.Az_Xml['Request']      =   '\n\r\t<REQUEST_ID>%s</REQUEST_ID>'
        self.Az_Xml['Connect']      =   '\n\r\t<CONNECTION_ID>%s</CONNECTION_ID>'
        self.Az_Xml['Object']       =   '\n\r\t<OBJECT>\n\r\t\t<_object_id>%s</_object_id>\n\r\t</OBJECT>'
        self.Az_Xml['Params_Begin'] =   '\n\r\t<PARAMS>'
        self.Az_Xml['Params']       =   '\n\r\t\t<ENTRY>%s</ENTRY>'
        self.Az_Xml['ParamsExtra']  =   '\n\r\t\t<ENTRY index="0">%s</ENTRY>'
        self.Az_Xml['Params_End']   =   '\n\r\t</PARAMS>'

        ## Azureus Network Info
        self.TIMEOUT                =   int(5.0)
        self.IP                     =   '192.168.0.1'
        self.PORT                   =   '6884'
        self.USER                   =   ''
        self.PASS                   =   ''
        self.URL                    =   'http://%s/process.cgi'
        self.LoginType              =   'BASIC'
        
        ## New Labels to Toggle Through..
        self.DNLABEL_               =   ['CompPct'  ,'Peers'    ,'Elapsed'  , 'Eta','Available','DownSpeed','Downloaded',
                                         'Tracker'  ,'UpSpeed'  ,'Uploaded' ,'Seeds'    ,'State'        ,'Ratio']
        self.UPLABEL_               =   ['Ratio'    ,'Seeds'    ,'Elapsed'  , 'Eta','Peers'    ,'Available','DownSpeed' ,
                                         'Downloaded','State'    ,'Tracker'  ,'UpSpeed'  ,'Uploaded' ,'CompPct']        

        self.KeyMenus               =   {'150': {'A':('Select/Action','','torrentmenu')             ,   \
                                                 'B':('Move Down','','moveDown')                    ,   \
                                                 'X':('Display Files','','showfiles')               ,   \
                                                 'Y':('Move Up','','moveUp')}                       ,   \
                                         '250': {'A':('Select/Action','','torrentmenu')             ,   \
                                                 'B':('Move Down','','moveDown')                    ,   \
                                                 'X':('Display Files','','showfiles')               ,   \
                                                 'Y':('Move Up','','moveUp')}                       ,   \
                                         '450': {'A':('Select/Action','','filemenu')                ,   \
                                                 'B':('Download Normal (All)','','all-normal')      ,   \
                                                 'X':('Back to Torrent View','','showtorrents')     ,   \
                                                 'Y':('Do Not Download (All)','','all-off')}        ,   \
                                         '16':  {'A':('Select/Action','','showentries')             ,   \
                                                 'B':('Set as Default','','setdefault')             ,   \
                                                 'X':('Azureus Config','','configmenu')             ,   \
                                                 'Y':('System Config','','systemmenu')}             ,   \
                                         '17':  {'A':('Select/Action','','showentries')             ,   \
                                                 'B':('Set as Default','','setdefault')             ,   \
                                                 'X':('Azureus Config','','configmenu')             ,   \
                                                 'Y':('System Config','','systemmenu')}             ,   \
                                         '26':  {'A':('Select/Action','','showentries')             ,   \
                                                 'B':('Set as Default','','setdefault')             ,   \
                                                 'X':('Azureus Config','','configmenu')             ,   \
                                                 'Y':('System Config','','systemmenu')}             ,   \
                                         '27':  {'A':('Select/Action','','showentries')             ,   \
                                                 'B':('Set as Default','','setdefault')             ,   \
                                                 'X':('Azureus Config','','configmenu')             ,   \
                                                 'Y':('System Config','','systemmenu')}             ,   \
                                         '46':  {'A':('Select/Action','','showentries')             ,   \
                                                 'B':('Set as Default','','setdefault')             ,   \
                                                 'X':('Azureus Config','','configmenu')             ,   \
                                                 'Y':('System Config','','systemmenu')}             ,   \
                                         '47':  {'A':('Select/Action','','showentries')             ,   \
                                                 'B':('Set as Default','','setdefault')             ,   \
                                                 'X':('Azureus Config','','configmenu')             ,   \
                                                 'Y':('System Config','','systemmenu')}             ,   \
                                         '0':   {'A':('Select/Action','','')}}

        
        ## Check against Read config data.
        if not (self.win.Config.has_key(self.Title))                :
            self.win.Config[self.Title]               = {}
        if not (self.win.Config[self.Title].has_key('IP'))          :
            self.win.Config[self.Title]['IP']         = self.IP
        if not (self.win.Config[self.Title].has_key('PORT'))        :
            self.win.Config[self.Title]['PORT']       = self.PORT
        if not (self.win.Config[self.Title].has_key('USER'))        :
            self.win.Config[self.Title]['USER']       = self.USER
        if not (self.win.Config[self.Title].has_key('PASS'))        :
            self.win.Config[self.Title]['PASS']       = self.PASS
        if not (self.win.Config[self.Title].has_key('TIMEOUT'))     :
            self.win.Config[self.Title]['TIMEOUT']    = self.TIMEOUT
        if not (self.win.Config[self.Title].has_key('DNLABEL_'))    :
            self.win.Config[self.Title]['DNLABEL_']    = self.DNLABEL_[0]
        if not (self.win.Config[self.Title].has_key('UPLABEL_'))    :
            self.win.Config[self.Title]['UPLABEL_']    = self.UPLABEL_[0]

        ### Pass these Parameters Back for Ease ###
        if not self.win.Modules.has_key('Ctrl')             :   self.win.Modules['Ctrl']    =   {} 
        self.win.Modules['Ctrl'][self.Title]                =   {}
        self.win.Modules['Ctrl'][self.Title]['Path']        =   PathName
        self.win.Modules['Ctrl'][self.Title]['FileType']    =   self.FileType

        ## Update all relevant Parameters ##
        self.UpdateAll()

####################################################################################################################
######## START ###################### COMMUNICATION ################################################################      
####################################################################################################################

    def UpdateAll(self) :
        ## Update the Variables
        self.UpdateUrl()
        self.UpdateLogin()
        self.UpdateTimeout()        


    def UpdateUrl(self) :
        ## Check Url Path against Read config data.
        self.FullUrl                =   self.URL   %  \
                                        str(self.win.Config[self.Title]['IP'] +':'+ self.win.Config[self.Title]['PORT'])

    def UpdateLogin(self)   :
        ## Update Login Info.
        try :
            self.Login = ''
            if self.win.Config[self.Title].has_key('USER') and self.win.Config[self.Title].has_key('PASS')  :
                if self.win.Config[self.Title]['USER'] != '' and self.win.Config[self.Title]['PASS'] != ''  :
                    self.Login =    str(self.win.Config[self.Title]['USER']) +':'+ str(self.win.Config[self.Title]['PASS'])
        except:
            traceback.print_exc()
            self.Login = ''


    def UpdateTimeout(self) :
        ## Update Timeout Info..
        try :
            self.TIMEOUT    =   int(self.win.Config[self.Title]['TIMEOUT'])
        except:
            traceback.print_exc()
            self.TIMEOUT    =   timeout


    def XmlHttp(self, Object='',Method='',Params='',ExtraO='NO') :
        try :
            self.win.xPrint('--XmlHttp')
            XMLString   =   ''
            XMLString   +=  self.Az_Xml['Begin']
            if Object   !=  ''  :   XMLString   +=  str(self.Az_Xml['Object']   % Object)
            XMLString   +=  str(self.Az_Xml['Method']   % Method)
            if  (type(Params) == TupleType  and len(Params) >  0 ) or \
                (type(Params) == StringType and Params      != '')  :
                XMLString   +=  str(self.Az_Xml['Params_Begin'])
                if type(Params) == TupleType :
                    for Pp in Params    :   XMLString   +=  str(self.Az_Xml['Params']  % Pp) 
                else :
                    if  ExtraO  ==  'NO'  :
                        ## Standard Call and display for Parameters..
                        XMLString   +=  str(self.Az_Xml['Params']       % Params)
                    else                                    :
                        ## Extra Params used as the Object-Id. This is only used for the addDownload[Torrent]
                        ## method as we need to input the object-id of the Torrent.
                        AddObj      =   str(self.Az_Xml['Object']       % Params)           
                        XMLString   +=  str(self.Az_Xml['ParamsExtra']  % AddObj)                       
                XMLString   +=  str(self.Az_Xml['Params_End'])
            if self.Comms.has_key('Connect')    :
                XMLString   +=  str(self.Az_Xml['Connect']   % self.Comms['Connect'])
            XMLString   +=  str(self.Az_Xml['Request']   % self.Comms['Request'])
            XMLString   +=  self.Az_Xml['End']
            ##print XMLString
            self.Comms['Request']   +=  1
            Answer = self.win.UrlThread(self.FullUrl                    ,   \
                                        post=XMLString                  ,   \
                                        login=self.Login                ,   \
                                        timeout=int(self.win.Config[self.Title]['TIMEOUT']))
            self.win.xPrint('++XmlHttp')
            return Answer
        except:
            traceback.print_exc()
            self.win.xPrint('==XmlHttp')
            return None


    def CheckResponse(self,data):
        try :
            self.win.xPrint('--CheckResponse')
            if reSearch('</RESPONSE>',data) or reSearch('<RESPONSE />',data) : return True
            else                                                             : return False
        except :
            traceback.print_exc()
            self.win.xPrint('==CheckResponse')
            return False

    def ClearVars(self):
        self.Comms                  =   {}


    def CheckComms(self):
        if (not self.Comms.has_key('Root')) or \
           (not self.Comms.has_key('Connect'))  :
                if ( self.InitConnection() )    :   return True
                else                            :   return False
        else                                    :   return True
        

    def InitConnection(self):
        try :
            self.win.xPrint('--InitConnection')
            ## Initialise Connection.
            self.ClearVars()
            self.Comms['Request']   =   int(tTime())
            Response                =   self.XmlHttp('','getSingleton')
            if Response ==  None    :   raise Exception
            self.Comms['Root']      =   core.ATag('_object_id',Response)
            self.Comms['Connect']   =   core.ATag('_connection_id',Response)
            self.win.xPrint('++InitConnection')
            return True
        except:
            #traceback.print_exc()
            self.win.xPrint('==InitConnection')
            return False


    def TorrentMgr(self)    :
        try     :
            ## Get TorrentManager from Root Object Id.
            print '--TorrentMgr'
            if ( self.DownloadMgr() )   :
                if (not self.Comms.has_key('TorrentManager'))    :
                    Response                        =   self.XmlHttp(self.Comms['Root'],'getTorrentManager')
                    if Response ==  None            :   raise Exception
                    self.Comms['TorrentManager']    =   core.ATag('_object_id',Response)
            else                        :
                return False
            print '++TorrentMgr'
            return True
        except:
            traceback.print_exc()
            print '==TorrentMgr'
            return False

        
    def DownloadMgr(self):
        try :
            ## Get Download Manager from Root Object Id.
            print '--DownloadMgr'
            if ( self.CheckComms() )    :
                if (not self.Comms.has_key('DlManager'))    :
                    Response                    =   self.XmlHttp(self.Comms['Root'],'getDownloadManager')
                    if Response ==  None        :   raise Exception
                    self.Comms['DlManager']     =   core.ATag('_object_id',Response)
            else                                :
                return False
            return True
            print '++DownloadMgr'
        except:
            traceback.print_exc()
            print '==DownloadMgr'
            return False
        

    def GetConfig(self):
        try :
            self.win.xPrint('--GetConfig')
            ## Get Plugin Config from Root Object Id.
            if ( self.CheckComms() )    :
                Response                =   self.XmlHttp(self.Comms['Root'],'getPluginconfig')
                if Response ==  None    :   raise Exception
                self.Comms['Config']    =   core.ATag('_object_id',Response)
                Exp                     =   reCompile('<ENTRY.*?>(.*?)</ENTRY>',reDotAll)
                Dta                     =   reFindall(Exp,Response)
                self.Comms['CfgData']   =   {}
                Size                    =   len(Dta) / 2
                for Chunk in range(Size):
                    self.Comms['CfgData'][Dta[Chunk]] = str(Dta[Chunk+10])
            else                        :
                return False
            self.win.xPrint('++GetConfig')
            return True
        except:
            traceback.print_exc()
            self.win.xPrint('==GetConfig')
            return False

####################################################################################################################
######## START ###################### MAIN ######## ################################################################      
####################################################################################################################

    def GetDownloads(self):
        self.win.xPrint('--GetDownloads')

        ## If its the first run then build Flag file and run the config first..
        FLAGFILE    =   str(self.win.Ctrl_) + str(self.Dir) +'\\first.run'
        if not (os.path.isfile(FLAGFILE))    :
            self.win.xPrint('** Config Needs to be run **')
            f = open(FLAGFILE,"wb")
            f.close()
            self.SystemMenu()
        
        Data        =   {}
        ## Run selection Based on Uploads,Downloads, Or Files..
        if      self.win.ViewState      ==  self.win.STATE_DOWN     :
            self.win.SiteLabel          =   'Azureus - Downloads ['+  str(self.win.Config[self.Title]['DNLABEL_']) +']'
            Data                        =   self.GetTorrents(self.win.Config[self.Title]['DNLABEL_'],'false',self.DNLABEL_)

        elif    self.win.ViewState      ==  self.win.STATE_UP       :
            self.win.SiteLabel          =   'Azureus - Uploads ['+ str(self.win.Config[self.Title]['UPLABEL_']) +']'
            Data                        =   self.GetTorrents(self.win.Config[self.Title]['UPLABEL_'],'true',self.UPLABEL_)

        elif    self.win.ViewState      ==  self.win.STATE_FILES    :
            self.win.SiteLabel          =   'Azureus - File Listing ['+ str(self.TORRENT) +']'
            Data                        =   self.GetFiles()
        self.win.xPrint('++GetDownloads')
        return Data       


    def GetTorrents(self,Label2,wanted,Extras):
        try :
            self.win.xPrint('--GetTorrents')            
            ## Initialise Variables that will be passed back ##
            Tor                     =   {}
            Tor_Array               =   []
            Queue                   =   0
            GlobalMsg               =   ''

            ## Now Retrieve the list of Torrents from Azureus ##
            if ( self.DownloadMgr() )   :
                Response                =   self.XmlHttp(self.Comms['DlManager'],'getDownloads')
                if Response ==  None    :   raise Exception

                ## Setup some temp Variables ##            
                _tmp                    =   []
                sp1                     =   0
                sp2                     =   0

                ## Compile options ##
                Filter                  =   reCompile(
                                              '<ENTRY index=\"(.*?)\">.*?'                      ##Entry     -   0
                                              '<_object_id>(.*?)</_object_id>.*?'               ##Id        -   1
                                              '<announce_result>.*?' 
                                              '<non_seed_count>(.*?)</non_seed_count>.*?'       ##nonseed   -   2
                                              '<seed_count>(.*?)</seed_count>.*?'               ##seed      -   3
                                              '<complete>(.*?)</complete>.*?'                   ##complete  -   4
                                              '<force_start>(.*?)</force_start>.*?'             ##force     -   5
                                              '<name>(.*?)</name>.*?'                           ##name      -   6
                                              '<paused>(.*?)</paused>.*?'                       ##paused    -   7
                                              '<position>(.*?)</position>.*?'                   ##position  -   8
                                              '<scrape_result>.*?'
                                              '<non_seed_count>(.*?)</non_seed_count>.*?'       ##nonseed   -   9
                                              '<seed_count>(.*?)</seed_count>.*?'               ##seed      -   10
                                              '<stats>.*?'
                                              '<availability>(.*?)</availability>.*?'           ##avail     -   11
                                              '<completed>(.*?)</completed>.*?'                 ##completed -   12
                                              '<download_average>(.*?)</download_average>.*?'   ##downavg   -   13
                                              '<downloaded>(.*?)</downloaded>.*?'               ##download  -   14
                                              '<elapsed_time>(.*?)</elapsed_time>.*?'           ##elapsed   -   15
                                              '<eta>(.*?)</eta>.*?'                             ##eta       -   16
                                              '<health>(.*?)</health>.*?'                       ##health    -   17
                                              '<share_ratio>(.*?)</share_ratio>.*?'             ##ratio     -   18
                                              '<status>(.*?)</status>.*?'                       ##status    -   19
                                              '<tracker_status>(.*?)</tracker_status>.*?'       ##tkrstat   -   20
                                              '<upload_average>(.*?)</upload_average>.*?'       ##uploadavg -   21
                                              '<uploaded>(.*?)</uploaded>'                      ##uploaded  -   22
                                              ,reDotAll)

                _data                   =   reFindall(Filter,Response)

                ##print 'Response :'
                ##print str(Response)
                
                ## Now loop through all the Data filtered and build a Dictionary from it.
                for _a in _data :
                    sp1 += int(_a[13])
                    sp2 += int(_a[21])
                    if str(_a[4]) == wanted : 
                        Nm                      =   str(_a[6])
                        Tor[Nm]                 =   {}
                        Tor[Nm]['Id']           =   str(_a[1])
                        Tor[Nm]['Peers']        =   str(_a[2])        +'('+ str(_a[9])          +')'
                        Tor[Nm]['Seeds']        =   str(_a[3])        +'('+ str(_a[10])         +')'
                        Tor[Nm]['Complete']     =   str(_a[4]).capitalize()
                        Tor[Nm]['ForceStart']   =   str(_a[5]).capitalize()
                        Tor[Nm]['Paused']       =   str(_a[7]).capitalize()
                        Tor[Nm]['Position']     =   int(_a[8])
                        Tor[Nm]['Available']    =   str(_a[11][:-3])
                        Tmp                     =   str(_a[12].rjust(4,'0'))
                        Tor[Nm]['CompPct']      =   (Tmp[:3] +'.'+ Tmp[-1:] +'%').strip('0')
                        Tor[Nm]['DownSpeed']    =   str(_a[13])[:-3]  +'.'+ str(_a[13])[-3:]    +' kBs'
                        Tor[Nm]['Downloaded']   =   str(int(_a[14]) / 1024)[:-3]                +' MB'
                        Tor[Nm]['Elapsed']      =   str(_a[15])
                        Tor[Nm]['Eta']          =   str(_a[16])
                        Tor[Nm]['Health']       =   str(_a[17])
                        Tmp                     =   str(_a[18].rjust(4,'0'))
                        Tor[Nm]['Ratio']        =   (Tmp[:1] +'.'+ Tmp[-3:] +'%').strip('0')
                        Tor[Nm]['State']        =   str(_a[19])
                        Tor[Nm]['Tracker']      =   str(_a[20])
                        Tor[Nm]['UpSpeed']      =   str(_a[21])[:-3]  +'.'+ str(_a[21])[-3:]    +' kBs'
                        Tor[Nm]['Uploaded']     =   str(int(_a[22]) / 1024)[:-3]                +' MB'
                        Queue                   +=  1
                        _tmp.append([int(_a[8]),Nm])
                _tmp.sort()

                ## Create the Listem that will be displayed..
                for Item in _tmp:
                    Health_Img  =   self.win.MEDIA +'health-'+ str(Tor[Item[1]]['Health']) +'.png'

                    ## Now Create Extra Information Tags to be displayed when focused.
                    ExtraInf    =   ''
                    for xtra in Extras  :
                        ExtraInf    +=   str(xtra)+':'+ str(Tor[Item[1]][str(xtra)])+ ' / '

                    TORITEM     =   xListItem(Item[1],Tor[Item[1]][Label2],ExtraInf,Health_Img)
                    Tor_Array.append(TORITEM)

                if (self.GetConfig()) :
                    GlobalMsg = 'Downloads: '                                                      + \
                                '['+ str(self.Comms['CfgData']['Max Download Speed KBs']) +'K] '   + \
                                str(sp1)[:-3].rjust(1,'0') + '.'                                   + \
                                str(sp1)[-3:-2].rjust(1,'0')                                       + \
                                ' kB/s    '                                                        + \
                                'Uploads: '                                                        + \
                                '['+ str(self.Comms['CfgData']['Max Upload Speed KBs'])   +'K] '   + \
                                str(sp2)[:-3].rjust(1,'0') + '.'                                   + \
                                str(sp2)[-3:-2].rjust(1,'0')                                       + \
                                ' kB/s'
            else    :
                return None
            self.win.xPrint('++GetTorrents')            
            return {'Torrents':Tor,'TorListItem':Tor_Array,'Queue':Queue,'GlobalMsg':GlobalMsg}         
        except:
            traceback.print_exc()
            self.win.xPrint('==GetTorrents')            
            return None


    def GetFiles(self) :
        try :
            self.win.xPrint('--GetFiles')
            ## Initialise Temp Variables
            Tor                     =   {}
            Tor_Array               =   []
            GlobalMsg               =   ''
            
            if not self.Comms.has_key('DiskManager') :
                Response    =   self.XmlHttp(self.FILEHASH,'getDiskManager')
                if Response ==  None    :   raise Exception
                Exp         =   reCompile('<_object_id>(.*?)</_object_id>',reDotAll)
                Obj         =   reFindall(Exp,Response)
                if len(Obj) ==  1   :   self.Comms['DiskManager']   =   str(Obj[0][0])
                else                :   self.Comms['DiskManager']   =   'Must Have Been Running'
                
            if self.Comms.has_key('DiskManager') or reSearch('RESPONSE',Response) :
                ## Data is Ok Continue
                Response    =   self.XmlHttp(self.FILEHASH,'getDiskManagerFileInfo')
                if Response ==  None    :   raise Exception
                Exp         =   reCompile('<ENTRY index=\"(\d+)\">.*?'
                                          '<_object_id>(.*?)</_object_id>.*?'
                                          '<file>(.*?)</file>.*?'
                                          '<is_priority>(.*?)</is_priority>.*?'
                                          '<is_skipped>(.*?)</is_skipped>.*?'
                                          '<length>(\d+)</length>.*?'
                                          '</ENTRY>',reDotAll)
                Tar = reFindall(Exp,Response)
                if len(Tar) > 0  :
                    ## We Have Data...
                    for No in range(len(Tar))   :
                        Nm                  =   str(os.path.basename(Tar[No][2]))
                        Tor[Nm]             =   {}
                        Tor[Nm]['Idx']      =   str(Tar[No][1])
                        Tor[Nm]['Pri']      =   str(Tar[No][3])
                        Tor[Nm]['Skip']     =   str(Tar[No][4])
                        Tor[Nm]['Size']     =   self.NiceSize(int(Tar[No][5]))
                        if   Tor[Nm]['Pri'] == 'false' and Tor[Nm]['Skip'] == 'false'   :   Health = 4
                        elif Tor[Nm]['Pri'] == 'true'  and Tor[Nm]['Skip'] == 'false'   :   Health = 2
                        elif Tor[Nm]['Pri'] == 'False' and Tor[Nm]['Skip'] == 'true'    :   Health = 5
                        else                                                            :   Health = 1
                        Tor[Nm]['Health']   =   str(Health)
                        Health_Img          =   self.win.MEDIA +'health-'+ str(Health) +'.png'
                        TORITEM             =   xListItem(str(Nm),str(Tor[Nm]['Size']),'No Additional Info',Health_Img)
                        Tor_Array.append(TORITEM)

                GlobalMsg      =   str(self.TORRENT)
                self.win.xPrint('++GetFiles')
                return {'Torrents':Tor,'TorListItem':Tor_Array,'GlobalMsg':GlobalMsg}
            else    :
                self.win.xPrint('++GetFiles')
                return None
        except:
            traceback.print_exc()
            self.win.xPrint('==GetFiles')
            return None
                    

    def NiceSize(self,Size) :
        try :
            Loops   =   0
            Arr     =   [' BYTES',' KB',' MB',' GB',' TB']
            while Size > 1024 :
                Size    =   Size / 1024
                Loops   =   Loops + 1
            return str(Size) + str(Arr[Loops])
        except:
            traceback.print_exc()
            return 'Unknown'


####################################################################################################################
######## START ###################### TORRENT/FILE ACTIONS #########################################################      
####################################################################################################################

    def KeyAction(self,Buttons,Labels):
        try :
            self.win.xPrint('--KeyAction: '+ str(Labels) +'-'+ str(Buttons))
            Action      =   Buttons[2]
            Options     =   []
            
            ## moveUp/Down for selected Torrent
            if      Action      == 'moveUp' or Action == 'moveDown'     :
                self.DownloadMgr()
                Object          =   self.win.Torrents[Labels[0]]['Id']            
                Response        =   self.XmlHttp(Object,Action)
                if Response ==  None    :   raise Exception
                return True,True
                
            ## Display Menu additional Options
            elif    Action      ==  'torrentmenu'   :
                Result = self.TorrentMenu(Labels[0])
                if ( Result )   :   return True,True
                else            :   return False,False

            ## Global Configuration Options
            elif    Action      ==  'configmenu'    :
                Result = self.ConfigMenu()
                if ( Result )   :   return True,True
                else            :   return False,False

            ## System Options
            elif    Action      ==  'systemmenu'    :
                self.SystemMenu()
                return True,False

            ## Files Menu Options
            elif    Action      ==  'filemenu'      :
                Result  =   self.FileMenu(Labels[0])
                if ( Result )   :   return True,True
                else            :   return False,False

            ## Set as Default
            elif    Action      ==  'setdefault'    :
                self.win.SetDefault(self.Title)
                return True,False

            ## Switch to Files View for the Torrent
            elif    Action      == 'showfiles'      :
                self.ViewState      =   self.win.ViewState
                self.win.ViewState  =   self.win.STATE_FILES
                self.FILEHASH       =   str(self.win.Torrents[Labels[0]]['Id'])
                self.TORRENT        =   str(Labels[0])
                return True,True

            ## Switch to Torrents View.
            elif    Action      ==  'showtorrents'  :
                self.win.ViewState  =   self.ViewState
                self.FILEHASH   =   ''
                self.TORRENT    =   ''
                return True,True
                
            ## Change all File entries for the Torrent
            elif    Action[:4]  ==  'all-'          :
                self.win.UpdateProgress(self._[14],0,self._[14])
                Method      =   'setSkipped[boolean]'
                if  Action[4:]  ==  'off'   :   Value       =   'true'
                else                        :   Value       =   'false'
                Total   =   len(self.win.Torrents.keys())
                Start   =   1
                for Key in self.win.Torrents.keys()     :
                    Pct     =   (Start*100)/Total
                    self.win.UpdateProgress(str(Key),Pct)
                    Response = self.XmlHttp(self.win.Torrents[Key]['Idx'],Method,Value)
                    if Response ==  None    :   raise Exception
                    tSleep(0.15)
                    Start += 1                
                self.win.UpdateProgress(self._[31],-1)
                return True,True

            ## Nothing To Do..
            self.win.xPrint('Cant Find anything to do.')
            self.win.xPrint('++KeyAction')
            return True,False
        except :
            traceback.print_exc()    
            self.win.UpdateProgress(self._[31],-1)
            self.win.xPrint('==KeyAction')
            return False,False


    ##good
    def FileMenu(self,Label): 
        try :
            self.win.xPrint('--FileMenu')
            Object          =   self.win.Torrents[Label]['Idx']
            Options         =   [[self._[70],0],[self._[72],1],[self._[73],2]]
            MenuList        =   []
            for List in Options     :   MenuList.append(List[0])
            Answer                  =   self.win.Menu.select(self._[14],MenuList)
            if Answer != -1         :
                Methods             =   []
                if      Options[Answer][1]  ==  0   :
                    Methods.append(['setSkipped[boolean]','true'])
                elif    Options[Answer][1]  ==  1   :
                    Methods.append(['setSkipped[boolean]','false'])
                    Methods.append(['setPriority[boolean]','false'])
                elif    Options[Answer][1]  ==  2   :
                    Methods.append(['setSkipped[boolean]','false'])
                    Methods.append(['setPriority[boolean]','true'])
                    
                for Item in Methods :
                    Response    =   self.XmlHttp(str(Object),str(Item[0]),str(Item[1]))
                    if Response ==  None    :   raise Exception
                return True

            self.win.xPrint('Nothing to Update')
            self.win.xPrint('++FileMenu')
            return True
        except:
            traceback.print_exc()
            self.win.xPrint('==FileMenu')
            return False
            

    ##good
    def TorrentMenu(self,Label) :
        try     :
            self.win.xPrint('--Torrent Menu')
            Options = []
            Rec     = self.win.Torrents[Label]
            if Rec['State'] != 'Stopped'        : Options.append([self._[6] ,'stop',''])
            else                                : Options.append([self._[5] ,'restart',''])
            if Rec['Position'] > 1              : Options.append([self._[7] ,'moveTo[int]','1'])
            if Rec['Position'] < self.win.Queue : Options.append([self._[8] ,'moveTo[int]',str(self.win.Queue)])
            if Rec['ForceStart'] == 'True'      : Options.append([self._[9] ,'setForceStart[boolean]','false'])
            else                                : Options.append([self._[10],'setForceStart[boolean]','true'])
            Options.append([self._[11],'remove',''])
            Options.append([self._[74],'remove[boolean,boolean]',('true','false')])
            Options.append([self._[44],'remove[boolean,boolean]',('true','true')])

            ## Display Menu:
            MenuList = []
            for List in Options     :
                MenuList.append(List[0])
            Answer = self.win.Menu.select(self._[14],MenuList)

            ## Process the answer..
            if Answer != -1 :
                self.DownloadMgr()
                Object = Rec['Id']
                if 'remove' in Options[Answer][1]:
                    YesNo = self.win.Menu.yesno(self._[17],self._[18],Label)
                    if not YesNo    :   self.win.xPrint('Dont do it!')
                    else            :
                        Response = self.XmlHttp(Object,'stop','')
                        if Response ==  None    :   raise Exception
                Response = self.XmlHttp(Object,Options[Answer][1],Options[Answer][2])
                if Response ==  None    :   raise Exception
                else                    :   return True
                
            self.win.xPrint('Nothing to Update')
            self.win.xPrint('++Torrent Menu')
            return True
        except:
            traceback.print_exc()
            self.win.xPrint('==Torrent Menu')
            return False


    ##good
    def ConfigMenu(self):
        try :
            self.win.xPrint('--ConfigMenu')
            
            Options     =   []
            ## Available Global Options:
            Options.append([self._[12],'resumeDownloads',''])
            Options.append([self._[13],'pauseDownloads',''])
            Options.append([self._[19],'stopAllDownloads',''])
            Options.append([self._[20],'startAllDownloads',''])

            ## Core Parameter configuration Options.
            Options.append(['Modify - Max Upload Speed KBs'                     ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Upload Speed When Only Seeding KBs'   ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Download Speed KBs'                   ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Connections Per Torrent'              ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Connections Global'                   ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Downloads'                            ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Active Torrents'                      ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Active Torrents When Only Seeding'    ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Uploads'                              ,'setIntParameter[String,int]',''])
            Options.append(['Modify - Max Uploads Seeding'                      ,'setIntParameter[String,int]',''])

            ## Display Menu:
            MenuList    =   []
            for List in Options     :
                MenuList.append(List[0])
            Answer = self.win.Menu.select(self._[14],MenuList)
            if Answer != -1         :
                if MenuList[Answer][:9] == 'Modify - ' :
                    ## Core parameter change requested.
                    Method  =   Options[Answer][1]
                    Param1  =   MenuList[Answer][9:]
                    Param2  =   self.win.Menu.numeric(0,str(Param1) +': ['+ str(self.Comms['CfgData'][Param1]) +']')
                    if Param2 != -1 :
                        ## Parameter OK.
                        Response = self.XmlHttp(str(self.Comms['Config']),Method,(str(Param1),str(Param2)))
                        if Response ==  None    :   raise Exception
                        else                    :   return True
                else                                    :
                    self.DownloadMgr()
                    if MenuList[Answer] == 'pauseDownloads' or \
                       MenuList[Answer] == 'resumeDownloads'    :   Object = self.Comms['DlManager']
                    Response = self.XmlHttp(Object,Options[Answer][1],Options[Answer][2])
                    if Response ==  None    :   raise Exception
                    else                    :   return True

            self.win.xPrint('Nothing to update..')
            self.win.xPrint('++ConfigMenu')
            return True
        except:
            traceback.print_exc()
            self.win.xPrint('==ConfigMenu')
            return False
            

    ##good
    def SystemMenu(self):
        try :
            self.win.xPrint('--SystemMenu')
            OK = False
            while not ( OK )    :            
                ## Available Configurations for Controller..
                ## 0 =  Display Name,   1 = Variable Name,  2 = Variable Type.
                Config      =   [['IP Address ['    + str(self.win.Config[self.Title]['IP'])        +']' ,'IP'       ,'IP']  , \
                                 ['Timeout ['       + str(self.win.Config[self.Title]['TIMEOUT'])   +']' ,'TIMEOUT'  ,'INT'] , \
                                 ['PORT Number ['   + str(self.win.Config[self.Title]['PORT'])      +']' ,'PORT'     ,'INT'] , \
                                 ['Username ['      + str(self.win.Config[self.Title]['USER'])      +']' ,'USER'     ,'TXT'] , \
                                 ['Password ['      + str(self.win.Config[self.Title]['PASS'])      +']' ,'PASS'     ,'TXT'] , \
                                 ['**** DONE ****'  ,'OK','OK']]
                
                ## Display Menu.
                MenuList            =   []
                for List in Config  :
                    MenuList.append(List[0])
                Answer = self.win.Menu.select(self._[14],MenuList)

                ## Now work on the Results.
                if Answer != -1         :
                    Result  =   -1
                    if      Config[Answer][2]   ==  'IP'    :
                        Result  =   self.win.Menu.numeric(3,str(MenuList[Answer]) +': ['+ \
                                                          str(self.win.Config[self.Title][Config[Answer][1]]) +']')

                    elif    Config[Answer][2]   ==  'INT'   :
                        Result  =   self.win.Menu.numeric(0,str(MenuList[Answer]) +': ['+ \
                                                          str(self.win.Config[self.Title][Config[Answer][1]]) +']')

                    elif    Config[Answer][2]   ==  'TXT'   :
                        Result  =   self.win.KeyText(str(self.win.Config[self.Title][Config[Answer][1]]),str(MenuList[Answer]))

                    elif    Config[Answer][2]   ==  'OK'   :
                        OK = True
                        
                    if Result == -1 or Result == '' :
                        self.win.xPrint('-1 or empty return so dont update it..')
                    else                            :
                        ## Clear the Cookie, Reset the Variables and Update config item..
                        #core.ClearCookie(str(self.win.Config[self.Title]['IP']))
                        self.win.Config[self.Title][Config[Answer][1]] = str(Result)
                        self.ClearVars()
                        self.UpdateAll()
                        self.win.ResetVars()
                else                    :
                    OK = True
            self.win.xPrint('++SystemMenu')
        except:
            traceback.print_exc()
            self.win.xPrint('==SystemMenu')
              

####################################################################################################################
######## START ###################### TORRENTS ADDED AND LISTED ####################################################      
####################################################################################################################


    ## New working code to add the torrent file from Disk into Azureus..
    ## TorrentFile is the disk filename of the downloaded Torrent.
    def SendTorrent(self,LookDir,TorrentFile):
        try :
            self.win.xPrint('--SendTorrent')
            ## Start Torrent Manager..
            if ( self.TorrentMgr() )    :
            
                ## Open File and create Hex String from it..
                f           =   open(LookDir + TorrentFile,"rb")
                data        =   f.read()
                f.close()
                HexStr      =   ''
                for i in range(len(data)):
                    HexStr += str("%02X " % ord(data[i:i+1])).strip()

                ## Now create the Torrent from the Hex string..
                Object      =   self.Comms['TorrentManager']
                Method      =   'createFromBEncodedData[byte[]]'
                Response    =   self.XmlHttp(Object,Method,HexStr)
                if Response ==  None    :   raise Exception
                else                    :   TorrentObj  =   core.ATag('_object_id',Response)

                ## Now Add the Torrent..
                Method      =   'addDownload[Torrent]'
                Response    =   self.XmlHttp(self.Comms['DlManager'],Method,str(TorrentObj),ExtraO='YES')
                if Response ==  None    :   raise Exception
                else                    :   self.win.xPrint('Torrent Added Ok')
                return True
            else                        :
                self.win.xPrint('** TorrentMgr Failed **')
                return False
        except :
            traceback.print_exc()
            self.win.xPrint('==SendTorrent')
            return False
